package de.fmannan.addbook.domainmodel;

import java.io.IOException;
import java.util.LinkedList;

import org.apache.log4j.Logger;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import de.fmannan.addbook.persistence.xmlwriter.XMLWriter;
import de.fmannan.addbook.views.ContactTableView;
import de.fmannan.addbook.views.ContactTreeView;

/**
 * @author fmannan
 * 
 * Contacts can be associated with a group and are stored in an internal list,
 * maintained by the group. It is not possible to create child-groups within a
 * parent-group.
 * 
 */
public class Group implements IContact{

	private static final Logger log = Logger.getLogger(Group.class);

	private String groupName;
	private String groupDescription;
	private IContact parent;
	private LinkedList<Contact> entries;
    private boolean isNewlyCreated;
	
	
	public Group(String groupName) {
		super();
		this.groupName = groupName != null ? groupName : "";
		this.groupDescription = "";
		this.entries = new LinkedList<Contact>();
		isNewlyCreated = true;
	}

	public Group(String groupName, String description) {
		super();
		this.groupName = groupName != null ? groupName : "";
		this.groupDescription = description != null ? description : "";
		this.entries = new LinkedList<Contact>();
		isNewlyCreated = true;
	}
	
	
	public String getGroupName() {
		return groupName;
	}

	public void setGroupName(String groupName) {
		this.groupName = groupName;
	}

	public void addContact(Contact contact) {
		entries.add(contact);
		contact.setParent(this);
		contact.setNewlyCreated(false);
		ContactTreeView.getInstance().refresh();
		if (ContactTableView.getInstance() != null)
			ContactTableView.getInstance().refresh();				
	}

	public void removeContact(Contact contact) {
		entries.remove(contact);
		contact.setParent(null);
		ContactTreeView.getInstance().refresh();
		if (ContactTableView.getInstance() != null)
			ContactTableView.getInstance().refresh();					
	}
	
	@Override
	public Object[] getChildren() {
		return entries.toArray();
	}

	@Override
	public Object getParent() {
		// the parent of all groups is the GroupRegistrar
		return GroupRegistrar.getInstance();
	}

	@Override
	public void setParent(IContact parent) {
		this.parent = parent;
		
	}
	
	@Override
	public boolean hasChildren() {
		return !entries.isEmpty();
	}

	@Override
	public Object getAdapter(Class adapter) {
		// TODO Auto-generated method stub
		return null;
	}

	public String toString() {
		return groupName;
	}

	public String getGroupDescription() {
		return groupDescription;
	}

	public void setGroupDescription(String groupDescription) {
		this.groupDescription = groupDescription;
	}

	public boolean isNewlyCreated() {
		return isNewlyCreated;
	}

	public void setNewlyCreated(boolean isNewlyCreated) {
		this.isNewlyCreated = isNewlyCreated;
	}
		

	@Override
	public void writeToXML(XMLWriter out) throws IOException {
		log.debug("Writing Group " + this.groupName + " to XML");
		
		// Write own attributes to XML
		out.writeAttribute("name", this.groupName);
		out.writeAttribute("description", this.groupDescription);
		out.writeAttribute("newlycreated", String.valueOf(this.isNewlyCreated));
		
		// Iterate over all Child-Contacts and delegate the writing to XML to
		// them
		for(Object o : getChildren()) {
			// Write the name of the Contact in the opening tag
			out.writeStartElement("contact");
			
			// Delegate the remaining XML-building to the Contact
			((Contact)o).writeToXML(out);
			
			// Close the Contact tag
			out.writeEndElement();	
		}
	}

	/**
	 * Builds a IContact item from XML Code.
	 * 
	 * @param node
	 *            the current node
	 * @return
	 */
	public static Group buildFromXML(Node node) {
		Group g = new Group((node.getAttributes().getNamedItem("name").getNodeValue()));
		g.setGroupDescription((node.getAttributes().getNamedItem("description").getNodeValue()));
		g.setNewlyCreated(Boolean.valueOf((node.getAttributes().getNamedItem("description").getNodeValue())));
		
		log.debug("Building Group from XML: " + g.getGroupName());
		
		NodeList contacts = node.getChildNodes();
		// Iterate over contacts and delegate building to them
		for(int i = 0; i < contacts.getLength(); i++) {
			g.addContact(Contact.buildFromXML(contacts.item(i)));
		}
		
		return g;
	}

}
